<html>
    <head>
        <title>Ajaxian RSS Bling: Dynamic RSS Reader</title>

        <link rel="stylesheet" type="text/css" href="rssbling.css"/>

        <script src="scripts/xmlhttprequest.js" type="text/javascript"></script>

        <script>
            var xhrFeedGetter;

            var oldFeedDiv;

            var feedIdArray = new Array();
            var feedCount = 0;
            var feedLoadCount = 0;

            var feedMap = {};

            var baseUrl = "rpc.bloglines.com";
            var proxyBaseUrl = "/proxy/";
            var useProxy = false;
            var saveDir = "/Users/bgalbs/tmp/rssdir";
            var offline = false;

            function getFeeds() {
				try {
					if (netscape.security.PrivilegeManager.enablePrivilege) {
						netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
					}
				} catch (ex) { // eat it
				}

                var xhr = new XMLHttpRequest();
                xhr.open("GET", ((useProxy) ? proxyBaseUrl : "http://") + baseUrl + "/listsubs", true);
                xhr.onreadystatechange = function() {
                    parseFeeds(xhr);
                };
                xhr.send(null);
            }

            function parseFeeds(xhr) {
                if (xhr.readyState == 4) {
                    try {
                        if (xhr.status == 200) {
                            buildFeeds(xhr.responseXML, xhr.responseText);
                        } else if (xhr.status == 401) {
                            alert("Username or password incorrect");
                        } else {
                            alert("Some kind of HTTP-related glitch occured.");
                        }
                    } catch (ex) {
                        offline = true;

                        if (netscape.security.PrivilegeManager.enablePrivilege) {
                            netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');

                            var file = Components.classes["@mozilla.org/file/local;1"].
                                createInstance(Components.interfaces.nsILocalFile);
                            file.initWithPath(saveDir + "/" + "feeds.xml");

                            var data = "";
                            var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]
                                .createInstance(Components.interfaces.nsIFileInputStream);
                            var sstream = Components.classes["@mozilla.org/scriptableinputstream;1"]
                                .createInstance(Components.interfaces.nsIScriptableInputStream);
                            fstream.init(file, 1, 0, false);
                            sstream.init(fstream);

                            var str = sstream.read(-1);
                            while (str.length > 0) {
                              data += str;
                              str = sstream.read(-1);
                            }

                            sstream.close();
                            fstream.close();

                            var parser = new DOMParser();
                            var dom = parser.parseFromString(data, "text/xml");

                            buildFeeds(dom, data);
                        }
                    }
                }
            }

            function buildFeeds(feedXML, feedText) {
                showLoading();

                if (!offline) {
                    if (netscape.security.PrivilegeManager.enablePrivilege) {
                        netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');

                        var file = Components.classes["@mozilla.org/file/local;1"].
                            createInstance(Components.interfaces.nsILocalFile);
                        file.initWithPath(saveDir + "/" + "feeds.xml");

                        // file is nsIFile, data is a string
                        var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
                            .createInstance(Components.interfaces.nsIFileOutputStream);

                        // use 0x02 | 0x10 to open file for appending.
                        foStream.init(file, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate
                        foStream.write(feedText, feedText.length);
                        foStream.close();
                    }
                }

				try {
					if (netscape.security.PrivilegeManager.enablePrivilege) {
						netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
					}
				} catch (ex) { // eat it
				}

                var outlines = feedXML.getElementsByTagName('outline');

                var feedContent = "";
                for (i = 0; i < outlines.length; i++) {
                    var outline = outlines[i];
                    var name = outline.getAttribute("title");
                    var subid = outline.getAttribute("BloglinesSubId");
                    if (subid != null) {
                        //feedContent += '<div class="unselectedFeed" onclick="getFeed(this, ' + subid + ')">' + name + '</div>';
                        feedContent += '<div class="disabledFeed" subid="' + subid + '">' + name + '</div>';
                        feedIdArray[feedCount++] = [subid,name];
                    }
                }

                var feedListContainer = document.getElementById('feedListContainer');
                feedListContainer.innerHTML = feedContent;

                backgroundLoadFeed(feedIdArray[feedLoadCount++]);
            }

            function backgroundLoadFeed(subid) {
                if (subid == null) return;

				try {
					if (netscape.security.PrivilegeManager.enablePrivilege) {
						netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
					}
				} catch (ex) { // eat it
				}

				document.getElementById("currentLoadingFeed").innerHTML = subid[1];

                var xhrBackground = new XMLHttpRequest();
                xhrBackground.onreadystatechange = function() {
                    backgroundParseFeed(subid[0], xhrBackground);
                }
                xhrBackground.open("GET", ((useProxy) ? proxyBaseUrl : "http://") + baseUrl + "/getitems?s=" + subid[0] + "&n=0", true);
                xhrBackground.send(null);
            }

            function backgroundParseFeed(feedId, xhrBackground) {
                if (xhrBackground.readyState == 4) {
                    try {
                        if (xhrBackground.status == 200) {
                            feedMap[feedId] = xhrBackground.responseXML;

                            if (netscape.security.PrivilegeManager.enablePrivilege) {
                                netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');

                                var file = Components.classes["@mozilla.org/file/local;1"].
                                    createInstance(Components.interfaces.nsILocalFile);
                                file.initWithPath(saveDir + "/" + feedId + ".xml");

                                // file is nsIFile, data is a string
                                var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
                                    .createInstance(Components.interfaces.nsIFileOutputStream);

                                // use 0x02 | 0x10 to open file for appending.
                                foStream.init(file, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate
                                foStream.write(xhrBackground.responseText, xhrBackground.responseText.length);
                                foStream.close();
                            }

                        }
                    } catch (ex) {
                        if (netscape.security.PrivilegeManager.enablePrivilege) {
                            netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');

                            try {
                                var file = Components.classes["@mozilla.org/file/local;1"].
                                    createInstance(Components.interfaces.nsILocalFile);
                                file.initWithPath(saveDir + "/" + feedId + ".xml");

                                var data = "";
                                var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]
                                    .createInstance(Components.interfaces.nsIFileInputStream);
                                var sstream = Components.classes["@mozilla.org/scriptableinputstream;1"]
                                    .createInstance(Components.interfaces.nsIScriptableInputStream);
                                fstream.init(file, 1, 0, false);
                                sstream.init(fstream);

                                var str = sstream.read(-1);
                                while (str.length > 0) {
                                  data += str;
                                  str = sstream.read(-1);
                                }

                                sstream.close();
                                fstream.close();

                                var parser = new DOMParser();
                                var dom = parser.parseFromString(data, "text/xml");

                                feedMap[feedId] = dom;
                            } catch (ex) {}
                        }

                    }
                    feedLoadCount++;
                    if (feedLoadCount >= feedIdArray.length) {
                        feedLoaded();
                    } else {
                         backgroundLoadFeed(feedIdArray[feedLoadCount]);
                    }
                }
            }

            function feedLoaded() {
                var feedListContainerDiv = document.getElementById("feedListContainer");
                var children = feedListContainerDiv.getElementsByTagName("div");
                for (i = 0; i < children.length; i++) {
                    var childDiv = children.item(i);
                    if (childDiv.className = "disabledFeed") {
                        childDiv.className = "unselectedFeed";
                        childDiv.setAttribute("onclick", "getFeed(this, " + childDiv.getAttribute("subid") + ")");
                    }
                }
                showNothing();
            }

            function getFeed(feedDiv, feedId) {
                if (oldFeedDiv != null) oldFeedDiv.className = "unselectedFeed";
                oldFeedDiv = feedDiv;

                feedDiv.className = "selectedFeed";

                var cachedXml = feedMap[feedId];
                if (cachedXml != null) {
                    buildFeed(cachedXml);
                    return;
                }

                showLoading();

                if (xhrFeedGetter != null) xhrFeedGetter.abort();
                xhrFeedGetter = new XMLHttpRequest();
				try {
					if (netscape.security.PrivilegeManager.enablePrivilege) {
						netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
					}
				} catch (ex) { // eat it
				}

                xhrFeedGetter.onreadystatechange = parseFeed;

                xhrFeedGetter.open("GET", ((useProxy) ? proxyBaseUrl : "http://") + baseUrl + "/getitems?s=" + feedId + "&n=0",
                         true);
                xhrFeedGetter.send(null);
            }

            function parseFeed() {
                if (xhrFeedGetter.readyState == 4) {
                    if (xhrFeedGetter.status == 200) {
                        buildFeed(xhrFeedGetter.responseXML);
                    } else if (xhrFeedGetter.status == 401) {
                        alert("Username or password incorrect");
                    } else {
                        //alert("Some kind of HTTP-related glitch occured.");
                        showError();
                    }
                }
            }

            function buildFeed(feedXML) {
                var feedDiv = document.getElementById("feedContent");
                feedDiv.innerHTML = "";

                if (feedXML == null) return;

				try {
					if (netscape.security.PrivilegeManager.enablePrivilege) {
						netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
					}
				} catch (ex) { // eat it
				}

                var channels = feedXML.getElementsByTagName("channel");
                if ((channels == null) || (channels.length == 0)) return;

                var html = "";
                for (i = 0; i < channels.length; i++) {
                    var channel = channels.item(i);
                    var title = getChildText(channel, "title");
                    var link = getChildText(channel, "link");
                    var description = getChildText(channel, "description");

                    html += '<div class="titlebar">';
                    html += '<div class="title"><a href="' + link + '">' + title + '</a></div>';
                    html += '<div class="description">' + description + '</div>';
                    html += '</div><div class="entries">';

                    var items = channel.getElementsByTagName("item");
                    for (z = 0; z < items.length; z++) {
                        var item = items.item(z);

                        var entryTitle = getChildText(item, "title");
                        var entryLink = getChildText(item, "link");
                        var entryDescription = getChildText(item, "description");

                        html += '<div class="entryTitle"><a href="' + entryLink + '">' + entryTitle + '</a></div>';
                        html += '<div class="entryText">' + entryDescription + '</div>';
                    }

                    html += "</div>";
                }
                feedDiv.innerHTML = html;
            }

            function getChildText(parent, childName) {
                var text = "";
                try {
                    text = parent.getElementsByTagName(childName).item(0).childNodes[0].nodeValue;
                } catch (e) {}
                return text;
            }

            function showError() {
                var html = "";
                html += '<table width="100%" height="100%">';
                html += '<tr><td valign="middle" align="center" class="error">';
                html += 'An error occured';
                html += '</td></tr></table>';
                showSomething(html);
            }

            function showLoading() {
                var html = "";
                html += '<table width="100%" height="100%">';
                html += '<tr><td valign="middle" align="center" class="status">';
                html += 'Loading feeds...<p/><span style="font-size: 9pt"><span id="currentLoadingFeed"></span></span>';
                html += '</td></tr></table>';
                showSomething(html);
            }

            function showNothing() {
                showSomething("");
            }

            function showSomething(html) {
                var feedContent = document.getElementById("feedContent");
                feedContent.innerHTML = html;
            }
        </script>
    </head>
    <body onload="getFeeds()">
        <table width="100%" height="100%">
            <tr>
                <td colspan="3">
                    <h1>
                        Ajaxian RSS Bling: Dynamic RSS Reader
                    </h1>
                </tr>
            </tr>
            <tr>
                <td height="100%" id="feedList" width="200" valign="top">
                    <div id="feedListContainer">
                    </div>
                </td>
                <td id="feedMenuSpacer">
                </td>
                <td id="feedContent" valign="top">
                </td>
            </tr>
        </table>
    </body>
</html>